﻿using System.Net;
using System.Runtime.Serialization;

namespace Toybox.NicoSharp.Video.MyPage
{
	using Abstracts;

	/// <summary>
	/// アイコンタイプ
	/// </summary>
	public enum IconId
	{
		Default1 = 0x00,
		Default2,
		White,
		Black,
		Red,
		Yellow,
		Green,
		Cyan,
		Blue,
		Purple,
	}

	/// <summary>
	/// ソートタイプ
	/// </summary>
	public enum SortType
	{
		Register_Old = 0x00,
		Register_New,
		MyListComment_Up,
		MyListComment_Down,
		Title_Up,
		Title_Down,
		Contribute_Up,
		Contribute_Down,
		Play_Large,
		Play_Small,
		Comment_New,
		Comment_Old,
		Comment_Large,
		Comment_Small,
		MyListRegist_Large,
		MyListRegist_Small,
		Time_Long,
		Time_Short,
		Page_Large,
		Page_Small,
	}

	public class MyListGroupItem
	{

		#region [Static]

		private const string FORMAT = "name={0}&description={1}&public={2}&default_sort{3}&icon_id={4}";

		#endregion [Static]


		#region Constructor

		public MyListGroupItem()
		{
			this.IsPublic = false;
			this.DefaultSort = SortType.Register_Old;
			this.IconId = MyPage.IconId.Default1;
		}

		public MyListGroupItem(MylistGroup.ListResult.Item item)
		{
			this.GroupId = item.id;

			this.Name = item.name;
			this.Description = item.description;

			this.IsPublic = item.ispublic;
			this.IconId = item.icon_id;
			this.DefaultSort = item.default_sort;
		}

		#endregion Constructor


		#region Public Members

		public string GroupId
		{
			get;
			internal set;
		}

		public string Name
		{
			get;
			set;
		}

		public string Description
		{
			get;
			set;
		}

		public bool IsPublic
		{
			get;
			set;
		}

		public SortType DefaultSort
		{
			get;
			set;
		}

		public IconId IconId
		{
			get;
			set;
		}

		#endregion Public Members


		#region Public Methods

		public string ToStringForAdd(bool isCompleted = false)
		{
			if (isCompleted)
				return string.Format(FORMAT, this.Name, this.Description, this.IsPublic ? "1" : "0", (int)this.DefaultSort, (int)this.IconId);
			else
			{
				string result = "name=" + this.Name;
				if (!string.IsNullOrEmpty(this.Description))
					result += "&description=" + this.Description;
				if (this.IsPublic)
					result += "&public=1";
				if (this.DefaultSort != SortType.Register_Old)
					result += "&default_sort=" + (int)this.DefaultSort;
				if (this.IconId != MyPage.IconId.Default1)
					result += "&icon_id=" + (int)this.IconId;

				return result;
			}
		}

		public string ToStringForUpdate()
		{
			string result = "group_id=" + this.GroupId + "&";
			result += string.Format(FORMAT,
				this.Name, this.Description, this.IsPublic ? "1" : "0", (int)this.DefaultSort, (int)this.IconId);
			return result;
		}

		#endregion Public Methods

		#region Override Methods

		public override string ToString()
		{
			return string.IsNullOrEmpty(this.Name) ?
				this.ToStringForAdd()
			: this.ToStringForUpdate();
		}

		#endregion Override Methods

	}

	public class MylistGroup : MyPagePrimitives.AbstractMyPageList
	{

		#region Constructor

		public MylistGroup(CookieCollection cookies = null)
			: base(cookies)
		{
			this.Token = new Token(NicoUrls.VideoTop + "my/");
			this.Token.Type = TokenType.GlobalHash;
		}

		#endregion Constructor


		#region Public Methods

		public ListResult List()
		{
			return this.Get<ListResult>(this.GetUrl("list"));
		}

		public GetResult Get(string group_id)
		{
			string url = GetUrl("get");
			string data = "group_id=" + group_id;
			return this.Post<GetResult>(url, data);
		}

		public AddResult Add(MyListGroupItem item)
		{
			if (this.Token.Expired) this.Token.Update();

			string url = GetUrl("add");
			string data = item.ToStringForAdd(false) + "&token=" + this.Token.Value;
			AddResult result = this.Post<AddResult>(url, data);

			if (result.status == "ok")
				item.GroupId = result.id;

			return result;
		}

		public UpdateResult Update(MyListGroupItem item)
		{
			if (this.Token.Expired) this.Token.Update();

			string url = GetUrl("update");
			string data = item.ToStringForUpdate() + "&token=" + this.Token.Value;
			return this.Post<UpdateResult>(url, data);
		}

		public DeleteResult Delete(string group_id)
		{
			if (this.Token.Expired) this.Token.Update();

			string url = GetUrl("delete");
			string data = "group_id=" + group_id + "&token=" + this.Token.Value;
			return this.Post<DeleteResult>(url, data);
		}

		public SortResult Sort(string[] group_id_list)
		{
			if (this.Token.Expired) this.Token.Update();

			string url = GetUrl("sort");

			string data = null;
			foreach (string group_id in group_id_list)
				data += "group_id_list[]=" + group_id + "&";
			data += "token=" + this.Token.Value;

			return this.Post<SortResult>(url, data);
		}

		#endregion Public Methods

		#region Protected Methods

		protected override string GetUrl(string method)
		{
			return NicoUrls.FlApi + "mylistgroup/" + method;
		}

		#endregion Protected Methods


		#region [SubClass]

		[DataContract]
		public class ListResult : AbstractStatus
		{
			[DataMember]
			public Item[] mylistgroup;

			#region [SubClass]

			[DataContract]
			public class Item
			{
				[DataMember]
				public string id;

				[DataMember]
				public string user_id;

				[DataMember]
				public string name;

				[DataMember]
				public string description;

				[DataMember(Name = "public")]
				public bool ispublic;

				[DataMember]
				public SortType default_sort;

				[DataMember]
				public int create_time;

				[DataMember]
				public int update_time;

				[DataMember]
				public int sort_order;

				[DataMember]
				public IconId icon_id;
			}

			#endregion [SubClass]
		}

		[DataContract]
		public class GetResult : AbstractStatus
		{
			[DataMember]
			public ListResult.Item mylistgroup;
		}

		[DataContract]
		public class AddResult : AbstractStatus
		{
			[DataMember]
			public string id;
		}

		[DataContract]
		public class UpdateResult : AbstractStatus
		{
		}

		[DataContract]
		public class DeleteResult : AbstractStatus
		{
		}

		[DataContract]
		public class SortResult : AbstractStatus
		{
			[DataMember]
			public string[] group_id_list;
		}

		#endregion [SubClass]

	}
}
